%% This file is part of Enblend.
%% Licence details can be found in the file COPYING.


\subsection[User-Defined Dynamic Functions]{\label{sec:user-defined-dynlink-functions}%
  \genidx{weighting!exposure!user-defined!dynamically-linked}%
  User-Defined, Dynamically-Linked Exposure Weighting Functions}

See also \sectionName~\ref{sec:user-defined-opencl-functions} below on defining weighting
functions via \acronym{OpenCL}.

\restrictednote{\acronym{Dynamic Linking}-enabled versions only.}

\genidx{linking!dynamic}%
\gensee{dynamic linking}{linking, dynamic}%
\genidx{loading!dynamic}%
\gensee{dynamic loading}{loading, dynamic}%
\genidx{shared object}%
\gensee{object!shared}{shared object}%
\genidx{dynamic library}%
\gensee{library!dynamic}{dynamic library}%
On operating systems, where dynamic linking (or synonymously: dynamic loading) of code is
possible, for \App{} executables compiled with dynamic-linking support (see
Section~\fullref{sec:finding-out-details} on how to check this feature), \App{} can work with
user-defined exposure weighting functions, passed with the long form of
option~\option{--exposure-weight-function}, load the exposure weight function identified by
\metavar{SYMBOL} from \metavar{SHARED-OBJECT} and optionally pass some \metavar{ARGUMENT}s:

\begin{literal}
  --exposure-weight-function=\metavar{SHARED-OBJECT}:\feasiblebreak
  \metavar{SYMBOL}\optional{:\feasiblebreak
    \metavar{ARGUMENT}\optional{:\dots}}%
  \optidx{--exposure-weight-function}
\end{literal}

Some notes on the arguments of this option:

\begin{itemize}
\item
  \metavar{SHARED-OBJECT} is a filename (typically ending in \filename{.so} or \filename{.dll}).
  Depending on the operating system and the dynamic-loader implementation compiled into \appcmd,
  \metavar{SHARED-OBJECT} may or may not require a path.

  \genidx{environment variable!LD\_LIBRARY\_PATH@\envvar{LD\_LIBRARY\_PATH}}%
  \gensee{LD\_LIBRARY\_PATH@\envvar{LD\_LIBRARY\_PATH}}%
         {environment variable, \envvar{LD\_LIBRARY\_PATH}}%
  \begin{restrictedmaterial}{Linux}
    If \metavar{SHARED-OBJECT} does not contain a slash (\sample{/}), the dynamic loader
    \emph{only} searches along \envvar{LD\_LIBRARY\_PATH}; it even ignores the current working
    directory unless \envvar{LD\_LIBRARY\_PATH} contains a dot (\sample{.}).  So, to use a
    \metavar{SHARED-OBJECT} living in the current directory either say
    \begin{literal}
      env LD\_LIBRARY\_PATH=\$LD\_LIBRARY\_PATH:. \bslash \\
      ~~~~\app{} --exposure-weight-function=\feasiblebreak SHARED-OBJECT:\dots
    \end{literal}
    or
    \begin{literal}
      \app{} --exposure-weight-function=\feasiblebreak ./SHARED-OBJECT:\dots
    \end{literal}

    \genidx{dlopen!Linux}%
    For details of the search algorithm please consult the manual page of \manpage{dlopen}{3}.
  \end{restrictedmaterial}

  \smallskip

  \genidx{environment variable!LD\_LIBRARY\_PATH@\envvar{LD\_LIBRARY\_PATH}}%
  \gensee{LD\_LIBRARY\_PATH@\envvar{LD\_LIBRARY\_PATH}}%
         {environment variable, \envvar{LD\_LIBRARY\_PATH}}%
  \genidx{environment variable!DYLD\_LIBRARY\_PATH@\envvar{DYLD\_LIBRARY\_PATH}}%
  \gensee{DYLD\_LIBRARY\_PATH@\envvar{DYLD\_LIBRARY\_PATH}}%
         {environment variable, \envvar{DYLD\_LIBRARY\_PATH}}%
  \genidx{environment variable!DYLD\_FALLBACK\_LIBRARY\_PATH@\envvar{DYLD\_FALLBACK\_LIBRARY\_PATH}}%
  \gensee{DYLD\_FALLBACK\_LIBRARY\_PATH@\envvar{DYLD\_FALLBACK\_LIBRARY\_PATH}}%
         {environment variable, \envvar{DYLD\_FALLBACK\_LIBRARY\_PATH}}%
  \begin{restrictedmaterial}{OS~X}
    \genidx{file!Mach-O}%
    \gensee{Math-O file}{file, Mach-O}%
    If \metavar{SHARED-OBJECT} does not contain a slash (\sample{/}), the dynamic loader
    searches the following paths or directories until it finds a compatible Mach-O~file:

    \begin{enumerate}
    \item \envvar{LD\_LIBRARY\_PATH},
    \item \envvar{DYLD\_LIBRARY\_PATH},
    \item current working directory, and finally
    \item \envvar{DYLD\_FALLBACK\_LIBRARY\_PATH}.
    \end{enumerate}

    \genidx{dlopen!OS~X}%
    For details of the search algorithm please consult the manual page of \manpage{dlopen}{3}.
  \end{restrictedmaterial}

  \smallskip

  \begin{restrictedmaterial}{Windows}
    If \metavar{SHARED-OBJECT} specifies an absolute filename, exactly this file is used.
    Otherwise \App{} searches in the following directories and in this order:

    \begin{enumerate}
    \item The directory from which \appcmd{} is loaded.
    \item The system directory.
    \item The Windows directory.
    \item The current directory.
    \item The directories that are listed in the \envvar{PATH}~environment variable.
    \end{enumerate}

    \genidx{LoadLibrary (Windows)}%
    For details consult the manual page of LoadLibrary.
  \end{restrictedmaterial}

\item
  There is no way knowing which of the symbols inside of \metavar{SHARED-OB\shyp
    JECT} are suitable for \metavar{SYMBOL} without knowledge of source code of
  \metavar{SHARED-OBJECT}.

\item
  A weight function has access to additional \metavar{ARGUMENT}s passed in by appending them
  after \metavar{SYMBOL} with the usual delimiters.  How these \metavar{ARGUMENT}s are
  interpreted and how many of them are required is encoded in the weight-function.  \App{}
  supports \metavar{ARGUMENT}s; it neither restricts their number nor their type.

  \begin{geeknote}%
    \optidx{--exposure-optimum}%
    \optidx{--exposure-width}%
    Usually, neither the exposure optimum
    (\option{--exposure-optimum}=\feasiblebreak\metavar{OPTIMUM}) nor the width
    (\option{--exposure-width}=\feasiblebreak\metavar{WIDTH}) of the exposure function are
    \metavar{ARGUMENT}s, because they are always explicitly passed on to any exposure weight
    function.
  \end{geeknote}

  For example, assuming \filename{variable\_power.cc} of the supplied examples was compiled to
  \filename{variable\_power.so}, we can override the default exponent of 2 with

  \begin{literal}
    \app{} --exposure-weight-function=\bslash \\
    ~~~~~~~~~variable\_power.so:vpower:1.8 \dots
  \end{literal}
\end{itemize}


\subsubsection[Prerequisites]{\label{sec:prerequisites}%
  \genidx{weighting!exposure!prerequisites}%
  Prerequisites}

To use a home-grown exposure-weight function several prerequisites must be met.  On the software
side

\begin{enumerate}
\item
  The operating system allows loading additional code during the execution of an application.

  \genidx{dynamic linking support}%
\item
  \App{} is compiled with the extra feature ``dynamic linking support''.

\item
  Either

  \begin{enumerate}
  \item
    The same compiler that compiled \App{} is available or at least

  \item
    A compiler that produces compatible object code to the compiler that compiled \App{}.
  \end{enumerate}

  The latter is called ``\acronym{ABI}-compatible''.  An example for a pair of
  \acronym{ABI}-compatible compilers is \acronym{GNU}'s~\command{g++} and
  \propername{Intel's}~\command{icpc}.

  \optidx{--show-software-components}%
  To find out which compiler built \emph{your} version of \appcmd{} use
  option~\option{--show\hyp soft\shyp ware\hyp com\shyp po\shyp
    nents}.

\item
  The base-class header file \filename{exposure\_weight\_base.h} is available.
\end{enumerate}

Between chair and keyboard:

\begin{itemize}
\item
  A firm understanding of weighting pixels in the fusion process and in particular in the
  cumulative ascription of different weights.

\item
  A basic understanding of object-oriented programming paired with the ability to compile and
  link single-source C++-files.

\item
  A realistic expectation of the limitations of tailoring weight functions.
\end{itemize}


\subsubsection[Coding Guidelines]{\label{sec:coding-guidelines}%
  \genidx{coding guidelines}%
  Coding Guidelines}

\begin{enumerate}
\item
  \begin{sloppypar}
    Derive the weight function from the supplied C++ base-class~\code{ExposureWeight}, which is
    defined in header file~\filename{exposure\_weight\_base.h}.  It resides in the
    \filename{src}~subdirectory of the source distribution and -- for a correctly installed
    package -- in directory \filename{\val*{val:DOCDIR}\slash examples\slash enfuse}.
  \end{sloppypar}

\item
  At least override member function~\code{weight}.

  \begin{itemize}
  \item
    Domain: define \code{weight} for normalized luminance values~\metavar{y} from zero to one
    including both interval ends: $0 \le y \le 1$.

  \item
    Image: Let the \code{weight}~$w$ fall in the interval from zero to one: $0 \le w \le 1$.
    The \code{weight}s can be all the same, $w = \mbox{const}$.  This is, they can encode a
    constant weight, as long as the constant is not zero.

    \App{} checks this property and refuses to continue if any weight is outside the required
    range or all weights are zero.

  \item
    (Optionally) Rescale the \metavar{WIDTH} of the function to match the \acronym{FWHM} of
    \App{}'s original Gauss curve.  The macro~\code{FWHM\_GAUSSIAN} is defined exactly to this
    end.
  \end{itemize}

\item
  If necessary, rewrite methods~\code{initialize} and \code{normalize}, too.

\item
  \restrictednote{\acronym{OpenMP}-enabled versions only.}

  \App{} never calls \code{initialize} in an \acronym{OpenMP} parallel execution environment.
  However, \acronym{OpenMP}-enabled versions of \App{} call \code{normalize} and \code{weight}
  in parallel sections.

  Technically, the functors which the user-defined weight functions are part of are
  copy-constructed for each \acronym{OpenMP} worker thread.  Thus, there is no contention within
  the derived classes of \code{ExposureWeight}.  Although, if \code{normalize} or \code{weight}
  access a shared resource these accesses must be protected by serialization instructions.  One
  solution is to use \acronym{OpenMP} directives, like for example,

  \begin{cxxlisting}
#pragma omp critical
{
    std::cout << "foobar!" << std::endl;
}
  \end{cxxlisting}

  Experienced hackers will recognize occasions when to prefer other constructs, like, for
  example \code{\#pragma omp atomic} or simply an atomic data-type (for example
  \code{sig\_atomic\_t} from \filename{signal.h}).

  Remember to compile all modules that use \acronym{OpenMP} directives with the
  (compiler-specific) flags that turn on \acronym{OpenMP}.  For \command{g++} this is
  \sample{-fopenmp} and for \command{icpc} it is \sample{-fopenmp} or \sample{-openmp}.

\item
  To raise an exception associated with the derived, user\hyp defined exposure\hyp weight class,
  throw
  \begin{literal}
    ExposureWeight::error(const std::string\& message)
  \end{literal}
  \App{} catches these exceptions at an enclosing scope, displays \metavar{message}, and
  terminates.

\item
  Define an object of the derived class.  This creates the \metavar{SYMBOL} to refer to at the
  \App{} command line.

  The actual signature of the constructor (default, two-argument, \dots) does not matter,
  because \App{} \emph{always} invokes \code{initialize} before calling any other member
  function of a user-defined, derived class of \code{ExposureWeight}.  Member
  function~\code{initialize} sets (read: overwrites) \metavar{optimum} and \metavar{width} and
  ensures they are within the required parameter range.
\end{enumerate}

\exampleName~\ref{ex:simple-dynamic-exposure-weight-function} shows the C++-code of a suitable
extension.  If \App{} has been compiled with support for user-defined weight functions, the
examples presented here should have been duplicated in
directory~\filename{\val*{val:DOCDIR}\slash examples\slash enfuse} along with a
\acronym{GNU}-Makefile called \filename{Makefile.userweight}.


\begin{exemplar}
  \begin{maxipage}
    \begin{cxxlisting}
#include <cmath>                     // std::fabs()

#include "exposure_weight_base.h"    // FWHM_GAUSSIAN, ExposureWeight

struct Linear : public ExposureWeight {
    void initialize(double y_optimum, double width_parameter,
                    ExposureWeight::argument_const_iterator arguments_begin,
                    ExposureWeight::argument_const_iterator arguments_end)
        override {
        ExposureWeight::initialize(y_optimum,
                                   width_parameter * FWHM_GAUSSIAN,
                                   arguments_begin, arguments_end);
    }

    double weight(double y) override {
        const double z = std::fabs(normalize(y));
        return z <= 1.0 ? 1.0 - z : 0.0;
    }
};

Linear linear;
    \end{cxxlisting}
  \end{maxipage}

  \caption[Simple dynamic exposure weight function]%
          {\label{ex:simple-dynamic-exposure-weight-function}%
            A dynamic exposure weight function that defines a ``roof-top''.  The natural width
            is exactly one, so we override member function~\code{initialize} to rescale
            \metavar{WIDTH}, passed in as \code{width\_parameter}, by multiplying with
            \code{FWHM\_GAUSSIAN} to get the same width as the predefined Gaussian.}
\end{exemplar}


As the extension language is C++, we can write templated families of functions, like
\exampleName~\ref{ex:templated-dynamic-exposure-weight-function} demonstrates.


\begin{exemplar}
  \begin{maxipage}
    \begin{cxxlisting}
#include <algorithm>    // std::max()
#include <cmath>        // M_LN2, std::exp(), std::fabs()

#include "exposure_weight_base.h" // FWHM_GAUSSIAN, ExposureWeight

template <int n> double ipower(double x) {return x * ipower<n - 1>(x);}
template <> double ipower<0>(double) {return 1.0;}

template <int n> struct TemplatedPower : public ExposureWeight {
    void initialize(double y_optimum, double width,
                    ExposureWeight::argument_const_iterator arguments_begin,
                    ExposureWeight::argument_const_iterator arguments_end)
        override {
        const double fwhm = 2.0 / std::exp(M_LN2 / static_cast<double>(n));
        ExposureWeight::initialize(y_optimum,
                                   width * FWHM_GAUSSIAN / fwhm,
                                   arguments_begin, arguments_end);
    }

    double weight(double y) override {
        return std::max(1.0 - ipower<n>(std::fabs(normalize(y))), 0.0);
    }
};

TemplatedPower<2> tpower2;
TemplatedPower<3> tpower3;
TemplatedPower<4> tpower4;
    \end{cxxlisting}
  \end{maxipage}

  \caption[Templated dynamic exposure weight function]%
          {\label{ex:templated-dynamic-exposure-weight-function}%
            The templated class~\code{TemplatedPower} allows to create a weight function for
            arbitrary positive exponents~\code{n}.  In particular, \code{TemplatedPower<4>}
            duplicates the built-in exposure-weight function~\code{bisquare}.}
\end{exemplar}


The last example, \ref{ex:variable-dynamic-exposure-weight-function}, shows a weight function
that accesses an extra \metavar{ARGUMENT} passed in with \option{--exposure-weight-function}.  A
class like \code{VariablePower} allows full control over the exponent at the command line
including fractional exponents thereby generalizing both of the previous examples.


\begin{exemplar}
  \begin{maxipage}
    \begin{cxxlisting}
#include <algorithm>    // std::max()
#include <cerrno>       // errno
#include <cmath>        // M_LN2, std::exp(), std::fabs(), std::pow()

#include "exposure_weight_base.h" // FWHM_GAUSSIAN, ExposureWeight


class VariablePower : public ExposureWeight {
    typedef ExposureWeight super;

public:
    void initialize(double y_optimum, double width,
                    ExposureWeight::argument_const_iterator arguments_begin,
                    ExposureWeight::argument_const_iterator arguments_end)
        override {
        if (arguments_begin == arguments_end) {
            exponent = 2.0;
        } else {
            char* tail;
            errno = 0;
            exponent = strtod(arguments_begin->c_str(), &tail);
            if (*tail != 0 || errno != 0) {
                throw super::error("non-numeric exponent");
            }
            if (exponent <= 0.0 || exponent > 4.0) {
                throw super::error("exponent x out of range 0 < x <= 4");
            }
        }

        const double fwhm = 2.0 / std::exp(M_LN2 / exponent);
        super::initialize(y_optimum, width * FWHM_GAUSSIAN / fwhm,
                          arguments_begin, arguments_end);
    }

    double weight(double y) override {
      return std::max(1.0 - std::pow(std::fabs(normalize(y)), exponent), 0.0);
    }

private:
    double exponent;
};

VariablePower vpower;
    \end{cxxlisting}
  \end{maxipage}

  \caption[Dynamic exposure weight function with extra arguments]%
          {\label{ex:variable-dynamic-exposure-weight-function}%
            Dynamic exposure weight function that accesses the first extra argument from the
            tuple of arguments passed with option~\option{--exposure-weight-function}.}
\end{exemplar}


\subsubsection[Performance Considerations]{\label{sec:performance-considerations}%
  \genidx{performance considerations}%
  Performance Considerations}

Exposure weighting objects are created and destroyed only $O(1)$~times.  Thus, member
function~\code{initialize} could be used to perform all kinds of computationally expensive
tasks.  In contrast, methods~\code{normalize} and \code{weight} are called for \emph{every}
pixel in \emph{each} of the input images.  Therefore, if performance of the weight function is a
problem, these two functions are the prime candidates for optimization.


\subsubsection[Compiling, Linking, and Loading]{\label{sec:compiling-linking-loading}%
  Compiling, Linking, and Loading}

\begin{restrictedmaterial}{Linux}
  \noindent Compile and link using the \uref{\gccgnuorg}{\acronym{GNU}-compiler}, \code{g++},
  for example with

  \begin{literal}
    g++ -std=c++11 \bslash \\
    ~~~~-O2 -fpic -I<PATH-TO-BASE-CLASS-HEADER> \bslash \\
    ~~~~-shared -Wl,-soname,dynexp.so \bslash \\
    ~~~~-o dynexp.so \bslash \\
    ~~~~dynexp.cc
  \end{literal}

  The important options are

  \begin{codelist}
  \item[\option{-fpic}]\itemend
    Instruct the compiler's code-generator to produce position\hyp{}independent code
    (\acronym{PIC}), which is suitable for a shared object.  Some systems require \sample{-fPIC}
    instead of \sample{-fpic}.

  \item[\option{-shared}]\itemend
    Tell the linker to create a shared object instead of the default executable.  On some
    systems, the library must be ``blessed'', by passing the shared-object name
    (\option{soname}) directly to the linker (\option{-Wl}).

    Of course more than one object file can be linked into a single shared object.
  \end{codelist}

  Finally, the weight function can be selected by its \metavar{SYMBOL}~name in the
  \metavar{SHARED-OBJECT}.

  \begin{literal}
    \app{} --exposure-weight-function=dynexp.so:linear\dots
  \end{literal}
\end{restrictedmaterial}

\medskip

\begin{restrictedmaterial}{OS~X}
  \noindent On OS~X the creation of shared objects -- or loadable modules -- has been tested
  with the C-language frontend of \uref{\llvm}{\acronym{LLVM}},
  \uref{\clangllvm}{\code{clang++}}, and should work on OS~X Mavericks~(10.9) or higher.

  \begin{literal}
    clang++ -std=c++11 -stdlib=libc++ \bslash \\
    ~~~~-O2 -bundle -I<PATH-TO-BASE-CLASS-HEADER> \bslash \\
    ~~~~-o dynexp.so \bslash \\
    ~~~~dynexp.cc
  \end{literal}

  The important option here is \sample{-bundle} which instructs the compiler's code-generator to
  produce a loadable module.

  Finally, the weight function can be selected by its \metavar{SYMBOL}~name in the
  \metavar{SHARED-OBJECT}.

  \begin{literal}
    \app{} --exposure-weight-function=dynexp.so:linear\dots
  \end{literal}
\end{restrictedmaterial}

\medskip

\begin{restrictedmaterial}{Windows}
  \noindent On Windows the creation of shared objects -- or dynamic link libraries
  (\acronym{DLL}~files) as they are called here -- has been tested with the \acronym{MinGW}
  compiler chain and with MS-Visual~C++~2012.

  \begin{itemize}
  \item
    Compile and link using the \acronym{MinGW} compiler with

    \begin{literal}
      g++ -g -O2 -I<PATH-TO-BASE-CLASS-HEADER> -c dynexp.cc \\
      g++ -g -shared -Wl,-soname,dynexp.dll -o dynexp.dll dynexp.o
    \end{literal}

    For details see the explanation for the \acronym{GNU} compiler above.  Windows neither
    requires options \option{-fpic} nor~\option{-fPIC}.

  \item
    When using the MS-Visual~C++~compiler, you need to explicitly export \metavar{SYMBOL}.
    There are two possibilities to achieve this.  Use only one variant, not both at the same
    time.

    \begin{enumerate}
    \item
      Either use \code{"C"}~linkage and define the object using the construction
      \code{\_\_declspec(dllexport)}.  For
      \exampleName~\ref{ex:simple-dynamic-exposure-weight-function} the object definition has to
      be extended to

      \begin{cxxlisting}
extern "C"
{
  __declspec(dllexport) Linear linear;
}
      \end{cxxlisting}

    \item
      Or, alternatively, create a module-definition file (\filename{.def}) and pass this file to
      the linker (in: \guielement{Project Properties}, \guielement{Linker}, \guielement{Module
        Definition File}).  For \exampleName~\ref{ex:simple-dynamic-exposure-weight-function},
      this file would look like

      \begin{literal}
        LIBRARY dynexp \\
        EXPORTS \\
        ~~~~~~~~linear @@1 \\
      \end{literal}
    \end{enumerate}
  \end{itemize}

  Finally, the weight function can be selected by its \metavar{SYMBOL} in the dynamic link
  library.

  \begin{literal}
    \app{} --exposure-weight-function=dynexp.dll:linear\dots
  \end{literal}
\end{restrictedmaterial}

\begin{optionsummary}
\item[--exposure-optimum] Section~\fullref{opt:exposure-optimum}
\item[--exposure-weight-function] Section~\fullref{opt:exposure-weight-function}
\item[--exposure-weight] Section~\fullref{opt:exposure-weight}
\item[--exposure-width] Section~\fullref{opt:exposure-width}
\item[--gray-projector] Section~\fullref{opt:gray-projector}
\end{optionsummary}


%%% Local Variables:
%%% fill-column: 96
%%% End:
